/*****************************************************************************/
/* Domino Operation System GUI Specific Module                               */
/*                                                                           */
/* Copyright (C) 2014 Laszlo Arvai                                           */
/* All rights reserved.                                                      */
/*                                                                           */
/* This software may be modified and distributed under the terms             */
/* of the BSD license.  See the LICENSE file for details.                    */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Includes
#include <krnlTypes.h>
#include <krnlString.h>
#include <guiTypes.h>
#include <guiColorGraphics.h>
#include <guiColorGraphicsDriver.h>

///////////////////////////////////////////////////////////////////////////////
// Module local variables

///////////////////////////////////////////////////////////////////////////////
// Local function prototypes
static void guiDrawMonochromeResourceBitmapBlock(guiCoordinate in_x, guiCoordinate in_y, dosWord in_width, dosWord in_height, dosROMAddress in_resource_address);


///////////////////////////////////////////////////////////////////////////////
// Initialize color graphics
void guiInitColorGraphics(void)
{
	guiInitColorGraphicsDriver();

	// init cliping rectangle
	g_gui_clip_rect.Left	= 0;
	g_gui_clip_rect.Top		= 0;
	g_gui_clip_rect.Right		= guiSCREEN_WIDTH-1;
	g_gui_clip_rect.Bottom	= guiSCREEN_HEIGHT-1;
}
  

///////////////////////////////////////////////////////////////////////////////
// Draw text
void guiDrawText( guiCoordinate in_x, guiCoordinate in_y, dosString in_string )
{
	dosROMAddress chardata;
	dosInt16 i;
	dosInt16 len;
	dosInt16 width;
	guiSize size;

	// check font
	if( g_gui_current_font.AsciiTableAddress == 0 )
		return;

	// check align
	if( g_gui_text_align != 0 )
	{
		// get text extent
		size = guiGetTextExtent( in_string );

		// horizontal align
		switch( g_gui_text_align & dosGUIHA_MASK )
		{
			// left align
			case dosGUIHA_LEFT:
				break;

			// center align
			case dosGUIHA_CENTER:
				in_x -= size.Width / 2;
				break;

			// right align
			case dosGUIHA_RIGHT:
				in_x -= size.Width;
				break;
		}

		// vertical align
		switch( g_gui_text_align & dosGUIVA_MASK )
		{
			// top align
			case dosGUIVA_TOP:
				break;

			// center align
			case dosGUIVA_CENTER:
				in_y -= size.Height / 2;
				break;

			// bottom align
			case dosGUIVA_BOTTOM:
				in_y -= size.Height;
				break;
		}
	}

	// draw characters
	len = strGetLength( in_string );
	for( i = 0; i < len; i++ )
	{
		if( in_string[i] >= g_gui_current_font.Minascii && in_string[i] <= g_gui_current_font.Maxascii )
		{
			chardata = dosROMReadWord( (in_string[i] - g_gui_current_font.Minascii) * sizeof( dosWord ) + g_gui_current_font.AsciiTableAddress );
			width = dosROMReadByte( chardata++ );

			guiDrawMonochromeResourceBitmapBlock(in_x, in_y, width, g_gui_current_font.Height, chardata);

			in_x += width;
		}
	}
}

static void guiDrawMonochromeResourceBitmapBlock(guiCoordinate in_x, guiCoordinate in_y, dosWord in_width, dosWord in_height, dosROMAddress in_resource_address)
{
	dosWord row_byte_count = (in_width + 7) / 8;
	dosByte bitmap_data;
	dosWord bitmap_x;
	dosWord bitmap_y;
	dosROMAddress row_start;
	dosWord bitmap_start_x = 0;
	dosWord bitmap_start_y = 0;
	dosWord bitmap_end_x = bitmap_start_x + in_width;
	dosWord bitmap_end_y = bitmap_start_y + in_height;

	for(bitmap_y = bitmap_start_y; bitmap_y < bitmap_end_y; bitmap_y++)
	{
		row_start = in_resource_address + row_byte_count * bitmap_y;

		if((bitmap_start_x % 8) != 0)
		{
			bitmap_data = dosROMReadByte(row_start + bitmap_start_x / 8);
			bitmap_data <<= (bitmap_start_x % 8);
		}

		for(bitmap_x = bitmap_start_x; bitmap_x < bitmap_end_x; bitmap_x++)
		{
			if((bitmap_x % 8) == 0)
				bitmap_data = dosROMReadByte(row_start + bitmap_x / 8);

			if((bitmap_data & 0x80) == 0)
			{
				guiSetBackgroundPixel(in_x + bitmap_x, in_y + bitmap_y);
			}
			else
			{
				guiSetForegroundPixel(in_x + bitmap_x, in_y + bitmap_y);
			}

			bitmap_data <<= 1;
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
// Draw circle
void guiDrawCircle(dosWord in_x, dosWord in_y, dosWord in_r)
{
	dosInt32 d;    /* Decision Variable */
  dosWord curX; /* Current X Value */
  dosWord curY; /* Current Y Value */
  
	if (in_r == 0)
		return;

	d = 3 - (in_r << 1);
  curX = 0;
  curY = in_r;

	while(curX <= curY) 
	{
		guiSetForegroundPixel(in_x + curX, in_y + curY);
		guiSetForegroundPixel(in_x + curX, in_y - curY);
    guiSetForegroundPixel(in_x - curX, in_y + curY);
    guiSetForegroundPixel(in_x - curX, in_y - curY);
    guiSetForegroundPixel(in_x + curY, in_y + curX);
    guiSetForegroundPixel(in_x + curY, in_y - curX);
    guiSetForegroundPixel(in_x - curY, in_y + curX);
    guiSetForegroundPixel(in_x - curY, in_y - curX);
   
    if (d < 0) {
      d += (curX << 2) + 6;
    } else {
      d += ((curX - curY) << 2) + 10;
      curY--;
    }
    curX++;
  }
}
